package cn.elwy.rcp.ui.explorer.core.handler;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipFile;

import cn.elwy.common.exception.RunException;
import cn.elwy.common.util.AssertUtil;
import cn.elwy.common.util.PathUtil;
import cn.elwy.common.util.io.FileUtil;
import cn.elwy.common.util.io.ListFileFilter;
import cn.elwy.common.util.io.ZipUtil;
import cn.elwy.osgi.config.ConfigContext;
import cn.elwy.rcp.core.model.ui.progress.ProgressMonitor;
import cn.elwy.rcp.ui.explorer.core.JarNameUtil;
import cn.elwy.rcp.ui.explorer.core.ManifestConst;
import cn.elwy.rcp.ui.explorer.core.PathConst;
import cn.elwy.rcp.ui.explorer.core.ProjectConst;
import cn.elwy.rcp.ui.explorer.core.util.MavenUtil;
import cn.elwy.rcp.ui.explorer.core.vo.BuilderModule;
import cn.elwy.rcp.ui.explorer.core.vo.ProjectConfig;

/**
 * 复制文件到输出目录
 * @author huangsq
 * @version 1.0, 2014-10-21
 * @since 1.0, 2014-10-21
 */
public class OutputFileHandler extends ProjectServiceHandler {

	private ListFileFilter listFileFilter;

	public OutputFileHandler() {
		listFileFilter = new ListFileFilter("^*.svn", true, true);
	}

	@Override
	public Object handler(ProjectConfig projectConfig, ProgressMonitor monitor) {
		/**
		 * 复制文档,sofa_2.2.0_yyyyMMddHHmmss/doc 复制演示代码,sofa_2.2.0_yyyyMMddHHmmss/demo 复制测试报告,sofa_2.2.0_yyyyMMddHHmmss/test
		 * 复制可执行,重新,sofa_2.2.0_yyyyMMddHHmmss/test 复制工具,sofa_2.2.0_yyyyMMddHHmmss/tools
		 */
		try {
			if (projectConfig.getPackType() != ProjectConst.PACK_TYPE_JAR) {
				if (projectConfig.getPackType() == ProjectConst.PACK_TYPE_WAR) {
					copyWar(projectConfig, monitor);
				} else if (projectConfig.getPackType() == ProjectConst.PACK_TYPE_INCREMENT_WAR) {
					copyIncrementWar(projectConfig, monitor);
				}
				copyDatabase(projectConfig, monitor);
				copyDoc(projectConfig, monitor);
				copyDemo(projectConfig, monitor);
				copySrc(projectConfig, monitor);
				copyTools(projectConfig, monitor);
			}
		} catch (IOException e) {
			throw new RunException(e.getMessage(), e);
		}
		return null;
	}

	/**
	 * 复制Demo
	 * @param projectConfig
	 * @param monitor
	 * @throws IOException
	 */
	private void copyDemo(ProjectConfig projectConfig, ProgressMonitor monitor) throws IOException {
		String demoDirectory = projectConfig.getDemoDirectory();
		if (AssertUtil.isNotEmpty(demoDirectory)) {
			String srcDemoPath = PathUtil.getAbsolutePath(projectConfig.getResourcePath(), demoDirectory);
			String outputDemoPath = PathUtil.getAbsolutePath(projectConfig.getOutputDir(), PathConst.OUTPUT_DEMO_DIR);
			FileUtil.deleteFile(outputDemoPath);
			FileUtil.copyFiles(srcDemoPath, outputDemoPath, true, listFileFilter);
		}
	}

	/**
	 * 复制Demo
	 * @param projectConfig
	 * @param monitor
	 * @throws IOException
	 */
	private void copySrc(ProjectConfig projectConfig, ProgressMonitor monitor) throws IOException {
		String srcDirectory = projectConfig.getSrcDirectory();
		if (AssertUtil.isNotEmpty(srcDirectory)) {
			String[] split = srcDirectory.split(",");
			int length = PathConst.OUTPUT_SRC_DIR.length;
			int i = 0;
			for (String it : split) {
				String srcDemoPath = PathUtil.getFilePath(projectConfig.getResourcePath(), it);
				String filePath = PathConst.OUTPUT_SRC_DIR[i];
				if (i >= length) {
					filePath = PathConst.OUTPUT_SRC_DIR[length - 1];
				}
				String outputDemoPath = PathUtil.getFilePath(projectConfig.getOutputDir(), filePath);
				FileUtil.cleanFile(outputDemoPath);
				FileUtil.copyFiles(srcDemoPath, outputDemoPath, true, listFileFilter);
				i++;
			}
		}
	}

	/**
	 * 复制Tools
	 * @param projectConfig
	 * @param monitor
	 * @throws IOException
	 */
	private void copyTools(ProjectConfig projectConfig, ProgressMonitor monitor) throws IOException {
		String toolsPath = projectConfig.getToolsPath();
		if (AssertUtil.isNotEmpty(toolsPath)) {
			String srcToolsPath = PathUtil.getAbsolutePath(projectConfig.getResourcePath(), toolsPath);
			String outputToolsPath = PathUtil.getAbsolutePath(projectConfig.getOutputDir(), PathConst.OUTPUT_TOOLS_DIR);
			FileUtil.deleteFile(outputToolsPath);
			FileUtil.copyFiles(srcToolsPath, outputToolsPath, true, listFileFilter);
		}
	}

	private void copyDoc(ProjectConfig projectConfig, ProgressMonitor monitor) throws IOException {
		String docDirectory = projectConfig.getDocDirectory();
		if (AssertUtil.isNotEmpty(docDirectory)) {
			String srcDocPath = PathUtil.getAbsolutePath(projectConfig.getResourcePath(), docDirectory);
			String outputDocPath = PathUtil.getFilePath(projectConfig.getOutputDir(), PathConst.OUTPUT_DOC_DIR);
			FileUtil.deleteFile(outputDocPath);
			FileUtil.copyFiles(srcDocPath, outputDocPath, true, listFileFilter);
		}
	}

	private void copyDatabase(ProjectConfig projectConfig, ProgressMonitor monitor) throws IOException {
		String dbScriptDirectory = projectConfig.getDbScriptDirectory();
		if (AssertUtil.isNotEmpty(dbScriptDirectory)) {

			String[] dirs = PathConst.SOURCE_SQL_PATHS;
			for (String dir : dirs) {
				String srcPath = PathUtil.getFilePath(projectConfig.getResourcePath(), dbScriptDirectory, dir);

				String destPath = PathUtil.getFilePath(projectConfig.getOutputDir(), PathConst.OUTPUT_SQL_DIR, dir);
				FileUtil.cleanFile(destPath);
				FileUtil.copyFiles(srcPath, destPath, true, listFileFilter);
			}
		}
	}

	private void copyWar(ProjectConfig projectConfig, ProgressMonitor monitor) throws IOException {
		String srcPath = PathUtil.getFilePath(projectConfig.getResourcePath(), projectConfig.getContainerDirectory());
		srcPath = PathUtil.getFilePath(srcPath, PathConst.TARGET);
		// , PathConst.WAR_NAME);
		File file = new File(srcPath);
		if (file.isDirectory()) {
			File files[] = file.listFiles();
			for (File f : files) {
				if (f.getName().endsWith(".war")) {

					String destPath = PathUtil.getFilePath(projectConfig.getOutputDir(), PathConst.OUTPUT_EXE_DIR, f.getName());
					FileUtil.deleteFile(destPath);
					FileUtil.copyFiles(f.getAbsolutePath(), destPath, true, listFileFilter);
					logger.info("复制文件到：" + destPath);
				}
			}
		}
	}

	private void copyIncrementWar(ProjectConfig pc, ProgressMonitor monitor) throws IOException {
		String warPath = pc.getWarPath();
		File f = new File(warPath);
		String destPath = "";
		String outExedir = PathUtil.getFilePath(pc.getOutputDir(), PathConst.OUTPUT_EXE_DIR);
		if (f.isFile()) {
			String shortFileName = FileUtil.getShortFileName(f);
			destPath = PathUtil.getFilePath(outExedir, shortFileName);
			ZipUtil.uncompress(warPath, destPath, false);
		} else {
			String shortFileName = f.getName();
			destPath = PathUtil.getFilePath(outExedir, shortFileName);
			FileUtil.copyFiles(warPath, destPath, true);
		}

		String containerDirectory = pc.getContainerDirectory();
		if (AssertUtil.isNotEmpty(containerDirectory)) {
			String filePath = PathUtil.getFilePath(pc.getResourcePath(), containerDirectory);
			if (!containerDirectory.startsWith("/")) {
				filePath = containerDirectory;
			}
			File pomFile = new File(filePath, "pom.xml");
			if (pomFile.exists()) {
				monitor.subTask(pomFile.toString());
				String[] cmd = { "clean" };
				File mavenHome = ConfigContext.getMavenHome();
				MavenUtil.execute(pomFile, mavenHome, Arrays.asList(cmd));
			}
			String copyFrom = PathUtil.getFilePath(filePath, "WebContent/META-INF");
			String copyTo = PathUtil.getFilePath(destPath, "META-INF");
			FileUtil.copyFiles(copyFrom, copyTo, true, listFileFilter);

			copyFrom = PathUtil.getFilePath(filePath, "WebContent/WEB-INF");
			copyTo = PathUtil.getFilePath(destPath, "WEB-INF");
			FileUtil.copyFiles(copyFrom, copyTo, true, listFileFilter);
		}

		String container = PathUtil.getFilePath(destPath, "WEB-INF/sofa-container");

		String updatePath = PathUtil.getFilePath(pc.getOutputDir(), PathConst.OUTPUT_EXE_UPDATE_DIR);

		File file = new File(updatePath);
		List<BuilderModule> blist = new ArrayList<BuilderModule>();

		getSelectedBuilderModule(file, blist, updatePath);

		for (BuilderModule bm : blist) {
			String filePath = bm.getFilePath();
			File file2 = new File(filePath);
			String name = file2.getName();

			final String srcName = JarNameUtil.getName(name);
			String outDirectory = bm.getOutDirectory();
			String filePath2 = PathUtil.getFilePath(container, outDirectory);

			File file3 = new File(filePath2);

			File[] listFiles = file3.listFiles(new FileFilter() {

				@Override
				public boolean accept(File pathname) {
					String targetName = JarNameUtil.getName(pathname.getName());
					return targetName.contains(srcName);
				}
			});

			boolean isCopy = false;
			if (listFiles != null) {
				JarFile jf1 = new JarFile(file2);
				Manifest manifest = jf1.getManifest();
				String v1 = manifest.getMainAttributes().getValue(ManifestConst.BUNDLE_SYMBOLIC_NAME);
				close(jf1);
				for (File file4 : listFiles) {
					JarFile jf2 = new JarFile(file4);
					String v2 = jf2.getManifest().getMainAttributes().getValue(ManifestConst.BUNDLE_SYMBOLIC_NAME);
					close(jf2);
					if (v1.equalsIgnoreCase(v2)) {
						FileUtil.deleteFile(file4);
						isCopy = FileUtil.copyFile(file2, file4.getParentFile(), file2.getName(), true);
					}
				}
			}
			if (!isCopy) {
				isCopy = FileUtil.copyFile(file2, new File(filePath2), file2.getName(), true);
			}
		}

		String filePath = PathUtil.getFilePath(outExedir, pc.getOutputFolder() + ".war");
		ZipUtil.compress(destPath, filePath);
		File file2 = new File(destPath);
		if (!FileUtil.deleteFile(file2)) {
			file2.deleteOnExit();
		}
	}

	private void getSelectedBuilderModule(File file, List<BuilderModule> bList, String updatePath) {
		if (file.isDirectory()) {
			File[] listFiles = file.listFiles();
			for (File child : listFiles) {
				if (child.isDirectory()) {
					getSelectedBuilderModule(child, bList, updatePath);
				} else if (child.getName().endsWith(".jar")) {
					BuilderModule bm = getBuilderModule(child, updatePath);
					bList.add(bm);
				}
			}
		} else if (file.getName().endsWith(".jar")) {
			BuilderModule bm = getBuilderModule(file, updatePath);
			bList.add(bm);
		}
	}

	private BuilderModule getBuilderModule(File file, String updatePath) {
		BuilderModule bm = new BuilderModule();
		String filePath = PathUtil.getFormatPath(file);
		String formatPath = PathUtil.getFormatPath(file.getParentFile());
		String replaceFirst = formatPath.replaceFirst(updatePath, "");
		String modulePath = replaceFirst + file.getName();
		bm.setFilePath(filePath);
		bm.setOutDirectory(replaceFirst);
		bm.setModulePath(modulePath);
		return bm;
	}

	private static void close(ZipFile zipFile) {
		try {
			if (zipFile != null)
				zipFile.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
